An author by another name
authorStephen Becker IV <github@deathbyescalator.com>
Mon, 16 May 2016 05:44:30 +0000 (22:44 -0700)
committerStephen Becker IV <github@deathbyescalator.com>
Mon, 16 May 2016 23:50:50 +0000 (16:50 -0700)
Dearest Reviewer

This is to support environment variables for name and email more like
git. This closes #1213 . I did look in to using libgit2 but I did not
see a clear way to get the author ident. This just moves from or_else
chaining to map_filter with env checks and getting the nth(0) result.

The docs I found
https://git-scm.com/book/en/v2/Git-Internals-Environment-Variables#Committing
do not really indicate an order of preference to the variables. I am
more then happy to rearrange the arrays in anyway.

Thanks for reviewing,
Becker

src/cargo/ops/cargo_new.rs
tests/test_cargo_new.rs

index f125622c927e36fe3768a3a3617ce537cde1fa81..2a878452c43a1646fea7ea3ca454e121eca9e0c0 100644 (file)
@@ -435,12 +435,20 @@ mod tests {
     Ok(())
 }
 
+fn get_environment_variable(variables: &[&str] ) -> Option<String>{
+    variables.iter()
+             .filter_map(|var| env::var(var).ok())
+             .next()
+}
+
 fn discover_author() -> CargoResult<(String, Option<String>)> {
     let git_config = GitConfig::open_default().ok();
     let git_config = git_config.as_ref();
+    let name_variables = ["NAME", "GIT_AUTHOR_NAME", "GIT_COMMITTER_NAME",
+                        "USER", "USERNAME"];
     let name = git_config.and_then(|g| g.get_string("user.name").ok())
-                         .or_else(|| env::var("USER").ok())      // unix
-                         .or_else(|| env::var("USERNAME").ok()); // windows
+                         .or_else(|| get_environment_variable(&name_variables));
+
     let name = match name {
         Some(name) => name,
         None => {
@@ -449,8 +457,9 @@ fn discover_author() -> CargoResult<(String, Option<String>)> {
                   username_var)
         }
     };
+    let email_variables = ["EMAIL", "GIT_AUTHOR_EMAIL", "GIT_COMMITTER_EMAIL"];
     let email = git_config.and_then(|g| g.get_string("user.email").ok())
-                          .or_else(|| env::var("EMAIL").ok());
+                          .or_else(|| get_environment_variable(&email_variables) );
 
     let name = name.trim().to_string();
     let email = email.map(|s| s.trim().to_string());
index 4a73925c230f9b995d177bd32100538e30e74b14..8a4330d656b91b20183786c42ba1ad06b298f664 100644 (file)
@@ -203,6 +203,37 @@ test!(finds_author_git {
     assert!(contents.contains(r#"authors = ["bar <baz>"]"#));
 });
 
+test!(finds_git_email{
+    let td = TempDir::new("cargo").unwrap();
+    assert_that(cargo_process("new").arg("foo")
+                                    .env("GIT_AUTHOR_NAME", "foo")
+                                    .env("GIT_AUTHOR_EMAIL", "gitfoo")
+                                    .cwd(td.path().clone()),
+                execs().with_status(0));
+
+    let toml = td.path().join("foo/Cargo.toml");
+    let mut contents = String::new();
+    File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
+    assert!(contents.contains(r#"authors = ["foo <gitfoo>"]"#), contents);
+});
+
+
+test!(finds_git_author{
+    // Use a temp dir to make sure we don't pick up .cargo/config somewhere in
+    // the hierarchy
+    let td = TempDir::new("cargo").unwrap();
+    assert_that(cargo_process("new").arg("foo")
+                                    .env_remove("USER")
+                                    .env("GIT_COMMITTER_NAME", "gitfoo")
+                                    .cwd(td.path().clone()),
+                execs().with_status(0));
+
+    let toml = td.path().join("foo/Cargo.toml");
+    let mut contents = String::new();
+    File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
+    assert!(contents.contains(r#"authors = ["gitfoo"]"#));
+});
+
 test!(author_prefers_cargo {
     ::process("git").args(&["config", "--global", "user.name", "foo"])
                     .exec().unwrap();